/*********************************************************************************/
/*                                                                               */
/*      PORT Driver                                                              */
/*                                                                               */
/*      Last updated by:   CBS                                                   */
/*      Last update date:  2013/1/25                                             */
/*      Revision:          0                                                     */
/*      Copyright:         DENS0                                                 */
/*                                                                               */
/*********************************************************************************/

/*********************************************************************************/
/*  include files                                                                */
/*********************************************************************************/
#include "MPC5674F_MVx264.h"
#include "Port.h"

/*********************************************************************************/
/*  prototypes                                                                   */
/*********************************************************************************/
static void Det_ReportError(U2 ModuleId, U1 InstanceId, U1 ApiId, U1 ErrorId);

/*********************************************************************************/
/*  defines  / macros                                                            */
/*********************************************************************************/

#if ( PORT_DEV_ERROR_DETECT == STD_ON )

   #define VALIDATE(_exp,_api,_err)                      \
     if( !(_exp) )                                       \
     {                                                   \
        Det_ReportError(MODULE_ID_PORT,0,_api,_err);     \
        return;                                          \
     }

#else

   #define VALIDATE(_exp,_api,_err)

#endif


#define EI_CALL() asm volatile (" wrteei 1 ")
#define DI_CALL() asm volatile (" wrteei 0 ")

/*********************************************************************************/
/*  constants / data types / structs / unions                                    */
/*********************************************************************************/

/* Moudule version information */
#if (PORT_VERSION_INFO_API == STD_ON)
static Std_VersionInfoType PORT_VersionInfoPtr =
{
    PORT_VENDOR_ID,
    PORT_MODULE_ID,
    PORT_INSTANCE_ID,
    PORT_SW_MAJOR_VERSION,
    PORT_SW_MINOR_VERSION,
    PORT_SW_PATCH_VERSION,
    PORT_AR_MAJOR_VERSION,
    PORT_AR_MINOR_VERSION,
    PORT_AR_PATCH_VERSION
};
#endif


typedef enum
{
    PORT_UNINITIALIZED = 0,
    PORT_INITIALIZED
} Port_StateType;

static Port_StateType PortState = PORT_UNINITIALIZED;
static const Port_ConfigType * PortCfgPtr = NULL;


/*********************************************************************************/
/*  API Functions                                                                */
/*********************************************************************************/

/************************************************************************************************************************/
/*  Service name        :   Port_Init                                                                                   */
/*  Sync/Async          :   Synchronous                                                                                 */
/*  Reentrancy          :   Non Reentrant                                                                               */
/*  Parameters (in)     :   Pointer to configuration set.                                                               */
/*  Return value        :   None                                                                                        */
/*  Discription         :   Initializes the Port Driver module.                                                         */
/************************************************************************************************************************/
void Port_Init(const Port_ConfigType* ConfigPtr)
{
    U2 i;
    volatile PCR_CfgType  * padConfig;
    volatile GPDO_CfgType * outConfig;

    VALIDATE((ConfigPtr != NULL), PORT_INIT_ID, PORT_E_PARAM_CONFIG);

    /* Pointers to the register memory areas */
    padConfig = &(SIU.PCR[0].R);
    outConfig = &(SIU.GPDO[0].R);

    /* Copy config to register areas */
    for(i=0;i<ConfigPtr->PinTotalNum;i++)
    {
       *(padConfig+i) = *(ConfigPtr->padConfig + i) | *(padConfig+i);

       if(0 == SIU.PCR[i].B.PA)
       {
          *(outConfig+i) = *(ConfigPtr->outConfig + i) | *(outConfig+i);
       }
       else
       {
          /* Pin level init value is unnecessary */
       }

    }

    PortState = PORT_INITIALIZED;
    PortCfgPtr = ConfigPtr;
}

/************************************************************************************************************************/
/*  Service name        :   Port_SetPinDirection                                                                        */
/*  Sync/Async          :   Synchronous                                                                                 */
/*  Reentrancy          :   Reentrant                                                                                   */
/*  Parameters (in)     :   Pin        Port Pin ID number.                                                              */
/*                          Mode       New Port Pin mode to be set on port pin.                                         */
/*  Return value        :   None                                                                                        */
/*  Discription         :   Sets the port pin direction.                                                                */
/************************************************************************************************************************/
#if (PORT_SET_PIN_DIRECTION_API == STD_ON)
void Port_SetPinDirection(Port_PinType Pin,Port_PinDirectionType Direction)
{
    VALIDATE((PortState == PORT_INITIALIZED),PORT_SET_PIN_DIRECTION_ID,PORT_E_UNINIT);
    VALIDATE((Pin < PORT_PIN_TOTAL_NUM), PORT_SET_PIN_DIRECTION_ID,PORT_E_PARAM_PIN);

    if (Direction == PORT_PIN_IN)
    {
       DI_CALL();

       SIU.PCR[Pin].B.IBE = 1;
       SIU.PCR[Pin].B.OBE = 0;

       EI_CALL();
    }
    else
    {
       DI_CALL();

       SIU.PCR[Pin].B.IBE = 0;
       SIU.PCR[Pin].B.OBE = 1;

       EI_CALL();
    }
    return;

}
#endif

/************************************************************************************************************************/
/*  Service name        :   Port_RefreshPortDirection                                                                   */
/*  Sync/Async          :   Synchronous                                                                                 */
/*  Reentrancy          :   Non Reentrant                                                                               */
/*  Parameters (in)     :   None                                                                                        */
/*  Return value        :   None                                                                                        */
/*  Discription         :   Refreshes port direction.                                                                   */
/************************************************************************************************************************/
void Port_RefreshPortDirection(void)
{
    volatile U2 * pcrPtr;
    const U2 * padCfgPtr;
    U2 bitMask,i;
    VALIDATE((PortState == PORT_INITIALIZED),PORT_REFRESH_PORT_DIRECTION_ID,PORT_E_UNINIT);

    pcrPtr = &(SIU.PCR[0].R);
    padCfgPtr = PortCfgPtr->padConfig;
    bitMask = PORT_IBE_ENABLE|PORT_OBE_ENABLE;

    for (i=0; i < PORT_PIN_TOTAL_NUM; i++)
    {
       if(PORT_DIRECTION_CHANGEABLE == *(PortCfgPtr->pinDirConfig+i))
       {
          DI_CALL();

          *pcrPtr = (*pcrPtr & ~bitMask) | (*padCfgPtr & bitMask);

          EI_CALL();
       }
       else
       {
            /* Port_RefreshPortDirection is forbidden */
       }

       pcrPtr++;
       padCfgPtr++;
    }

}

/************************************************************************************************************************/
/*  Service name        :   Port_SetPinMode                                                                             */
/*  Sync/Async          :   Synchronous                                                                                 */
/*  Reentrancy          :   Reentrant                                                                                   */
/*  Parameters (in)     :   Pin        Port Pin ID number.                                                              */
/*                          Mode       New Port Pin mode to be set on port pin.                                         */
/*  Return value        :   None                                                                                        */
/*  Discription         :   Sets the port pin mode.                                                                     */
/************************************************************************************************************************/
#if (PORT_SET_PIN_MODE_API == STD_ON)
void Port_SetPinMode(Port_PinType Pin,Port_PinModeType Mode)
{
    U2 bitMask;
    VALIDATE((PortState == PORT_INITIALIZED),PORT_SET_PIN_MODE_ID,PORT_E_UNINIT);
    VALIDATE((Pin < PORT_PIN_TOTAL_NUM), PORT_SET_PIN_MODE_ID,PORT_E_PARAM_PIN);


    bitMask = (PORT_PA2_BIT|PORT_PA1_BIT|PORT_PA0_BIT);

    if(PORT_MODE_CHANGEABLE == *(PortCfgPtr->pinDirConfig+Pin))
    {
        DI_CALL();

        SIU.PCR[Pin].R = (SIU.PCR[Pin].R  & (~bitMask)) | Mode;

        EI_CALL();
    }
    else
    {
        /* Port_SetPinMode is forbidden */
    }
}
#endif

/************************************************************************************************************************/
/*  Service name        :   Port_GetVersionInfo                                                                         */
/*  Sync/Async          :   Synchronous                                                                                 */
/*  Reentrancy          :   Non Reentrant                                                                               */
/*  Parameters (out)    :   versioninfo         Pointer to where to store the version information of this module.       */
/*  Return value        :   None                                                                                        */
/*  Description         :   Returns the version information of this module.                                             */
/************************************************************************************************************************/
#if (PORT_VERSION_INFO_API == STD_ON)
void Port_GetVersionInfoPtr(Std_VersionInfoType* versioninfo)
{
   versioninfo->vendorID = PORT_VersionInfoPtr.vendorID;
   versioninfo->moduleID = PORT_VersionInfoPtr.moduleID;
   versioninfo->instanceID = PORT_VersionInfoPtr.instanceID;

   versioninfo->sw_major_version = PORT_VersionInfoPtr.sw_major_version;
   versioninfo->sw_minor_version = PORT_VersionInfoPtr.sw_minor_version;
   versioninfo->sw_patch_version = PORT_VersionInfoPtr.sw_patch_version;

   versioninfo->ar_major_version = PORT_VersionInfoPtr.ar_major_version;
   versioninfo->ar_minor_version = PORT_VersionInfoPtr.ar_minor_version;
   versioninfo->ar_patch_version = PORT_VersionInfoPtr.ar_patch_version;

   VALIDATE( (versioninfo != NULL ), PORT_GET_VERSION_INFO_ID, PORT_E_PARAM_CONFIG );
}
#endif

/*********************************************************************************/
/*  Local Functions                                                              */
/*********************************************************************************/

void Det_ReportError(U2 ModuleId, U1 InstanceId, U1 ApiId, U1 ErrorId)
{
    /* error report! */
}
/*-- End Of File -------------------------------------------------------*/